﻿

using CCSFPCLoaderUI.Data;
using CCSFPCLoaderUI.Services;
using HalconDotNet;
using MvCamCtrl.NET;
using NLog;
using Prism.Commands;
using Prism.Ioc;
using Prism.Mvvm;
using System;
using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using ViewROI;

namespace CCSFPCLoaderUI.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        #region 变量
        private static Logger logger = LogManager.GetCurrentClassLogger();
        private readonly IHIKCameraService leftCamera, rightCamera;
        #endregion
        #region 属性
        public string Title { get; set; } = "CCSFPCLoaderUI";
        public string Version { get; set; } = "1.0.0";
        private string partNum;
        public string PartNum
        {
            get { return partNum; }
            set { SetProperty(ref partNum, value); }
        }
        private string messageStr;
        public string MessageStr
        {
            get { return messageStr; }
            set { SetProperty(ref messageStr, value); }
        }
        private bool pLCState;
        public bool PLCState
        {
            get { return pLCState; }
            set { SetProperty(ref pLCState, value); }
        }
        private bool lCameraState;
        public bool LCameraState
        {
            get { return lCameraState; }
            set { SetProperty(ref lCameraState, value); }
        }
        private bool rCameraState;
        public bool RCameraState
        {
            get { return rCameraState; }
            set { SetProperty(ref rCameraState, value); }
        }
        #region 1#
        private HImage cameraImage1;
        public HImage CameraImage1
        {
            get { return cameraImage1; }
            set { SetProperty(ref cameraImage1, value); }
        }
        private bool cameraRepaint1;
        public bool CameraRepaint1
        {
            get { return cameraRepaint1; }
            set { SetProperty(ref cameraRepaint1, value); }
        }
        private ObservableCollection<ROI> cameraROIList1 = new ObservableCollection<ROI>();
        public ObservableCollection<ROI> CameraROIList1
        {
            get { return cameraROIList1; }
            set { SetProperty(ref cameraROIList1, value); }
        }
        private HObject cameraAppendHObject1;
        public HObject CameraAppendHObject1
        {
            get { return cameraAppendHObject1; }
            set { SetProperty(ref cameraAppendHObject1, value); }
        }
        private HMsgEntry cameraAppendHMessage1;
        public HMsgEntry CameraAppendHMessage1
        {
            get { return cameraAppendHMessage1; }
            set { SetProperty(ref cameraAppendHMessage1, value); }
        }
        private Tuple<string, object> cameraGCStyle1;
        public Tuple<string, object> CameraGCStyle1
        {
            get { return cameraGCStyle1; }
            set { SetProperty(ref cameraGCStyle1, value); }
        }
        #endregion
        #region 2#
        private HImage cameraImage2;
        public HImage CameraImage2
        {
            get { return cameraImage2; }
            set { SetProperty(ref cameraImage2, value); }
        }
        private bool cameraRepaint2;
        public bool CameraRepaint2
        {
            get { return cameraRepaint2; }
            set { SetProperty(ref cameraRepaint2, value); }
        }
        private ObservableCollection<ROI> cameraROIList2 = new ObservableCollection<ROI>();
        public ObservableCollection<ROI> CameraROIList2
        {
            get { return cameraROIList2; }
            set { SetProperty(ref cameraROIList2, value); }
        }
        private HObject cameraAppendHObject2;
        public HObject CameraAppendHObject2
        {
            get { return cameraAppendHObject2; }
            set { SetProperty(ref cameraAppendHObject2, value); }
        }
        private HMsgEntry cameraAppendHMessage2;
        public HMsgEntry CameraAppendHMessage2
        {
            get { return cameraAppendHMessage2; }
            set { SetProperty(ref cameraAppendHMessage2, value); }
        }
        private Tuple<string, object> cameraGCStyle2;
        public Tuple<string, object> CameraGCStyle2
        {
            get { return cameraGCStyle2; }
            set { SetProperty(ref cameraGCStyle2, value); }
        }
        #endregion
        #endregion
        #region 方法绑定
        private DelegateCommand<object> appLoadedEventCommand;
        public DelegateCommand<object> AppLoadedEventCommand =>
            appLoadedEventCommand ?? (appLoadedEventCommand = new DelegateCommand<object>(ExecuteAppLoadedEventCommand));
        private DelegateCommand appClosedEventCommand;
        public DelegateCommand AppClosedEventCommand =>
            appClosedEventCommand ?? (appClosedEventCommand = new DelegateCommand(ExecuteAppClosedEventCommand));

        void ExecuteAppClosedEventCommand()
        {
            leftCamera.StopGrabe();
            leftCamera.CloseCamera();
        }
        async void ExecuteAppLoadedEventCommand(object obj)
        {
            await Task.Run(() => {
                try
                {
                    using var mdb = new MDbContext();
                    var _partnum = mdb.PartNums.FirstOrDefault(part => part.IsSelect);
                    if (_partnum != null) {
                        PartNum = _partnum.Name;
                    }

                    var _param = mdb.MParams.FirstOrDefault(param => param.Name == "CameraIP" && param.Hand == 0);
                    if (_param != null)
                    {
                        var r = leftCamera.OpenCamera(_param.Value);
                        LCameraState = r;
                        if (!r)
                        {
                            addMessage("左相机连接失败");
                        }
                        else
                        {
                            leftCamera.StartGrabe();
                            while (true)
                            {
                                var res = leftCamera.ImageQueue.TryDequeue(out var img);
                                if (res)
                                {
                                    CameraImage1 = new HImage(img);
                                }
                                Thread.Sleep(100);
                            }
                  
                        }
                    }
                  

                    addMessage("软件加载完成");
                }
                catch (Exception ex)
                {
                    addMessage(ex.Message);
                }
            });
        }
        #endregion
        #region 构造函数
        void ImageCallbackFunc1(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
        {
            if (leftCamera.m_bIsDeviceOpen)
            {
                if (leftCamera.m_bIsDeviceOpen && pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB8)
                {
                    try
                    {
                        IntPtr pImageBuffer = Marshal.AllocHGlobal((int)leftCamera.PayloadSize * 3);
                        var nRet = leftCamera.ConvertToRGB(pData, pFrameInfo.nHeight, pFrameInfo.nWidth, pFrameInfo.enPixelType, pImageBuffer);
                        HObject Hobj;
                        int imageSize = (int)(pFrameInfo.nWidth * pFrameInfo.nHeight * 3);
                        byte[] imageData = new byte[imageSize];
                        Marshal.Copy(pImageBuffer, imageData, 0, imageSize);
                        GCHandle pinnedArray = GCHandle.Alloc(imageData, GCHandleType.Pinned);
                        IntPtr ptr = pinnedArray.AddrOfPinnedObject();
                        HOperatorSet.GenImageInterleaved(out Hobj, ptr, "rgb", pFrameInfo.nWidth, pFrameInfo.nHeight, -1, "byte", 0, 0, 0, 0, -1, 0);
                        leftCamera.ImageQueue.Enqueue(Hobj.CopyObj(1, -1));
                        Hobj.Dispose();
                        pinnedArray.Free();
                        Marshal.FreeHGlobal(pImageBuffer);
                    }
                    catch (Exception ex)
                    {
                        logger.Error(ex);
                    }
                }
            }
        }
        void ImageCallbackFunc2(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
        {
            if (rightCamera.m_bIsDeviceOpen)
            {
                if (rightCamera.m_bIsDeviceOpen && pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG8)
                {
                    try
                    {
                        IntPtr pImageBuffer = Marshal.AllocHGlobal((int)rightCamera.PayloadSize * 3);
                        var nRet = rightCamera.ConvertToRGB(pData, pFrameInfo.nHeight, pFrameInfo.nWidth, pFrameInfo.enPixelType, pImageBuffer);
                        HObject Hobj;
                        int imageSize = (int)(pFrameInfo.nWidth * pFrameInfo.nHeight * 3);
                        byte[] imageData = new byte[imageSize];
                        Marshal.Copy(pImageBuffer, imageData, 0, imageSize);
                        GCHandle pinnedArray = GCHandle.Alloc(imageData, GCHandleType.Pinned);
                        IntPtr ptr = pinnedArray.AddrOfPinnedObject();
                        HOperatorSet.GenImageInterleaved(out Hobj, ptr, "rgb", pFrameInfo.nWidth, pFrameInfo.nHeight, -1, "byte", 0, 0, 0, 0, -1, 0);
                        rightCamera.ImageQueue.Enqueue(Hobj.CopyObj(1, -1));
                        Hobj.Dispose();
                        pinnedArray.Free();
                        Marshal.FreeHGlobal(pImageBuffer);
                    }
                    catch (Exception ex)
                    {
                        logger.Error(ex);
                    }
                }
            }
        }
        public MainWindowViewModel(IContainerProvider containerProvider)
        {
            MessageStr = string.Empty;
            NlogConfig();
            leftCamera = containerProvider.Resolve<IHIKCameraService>("LeftCamera");
            leftCamera.ImageQueue = new ConcurrentQueue<HObject>();
            leftCamera.ImageCallbackFunc = ImageCallbackFunc1;
            rightCamera = containerProvider.Resolve<IHIKCameraService>("RightCamera");
            rightCamera.ImageQueue = new ConcurrentQueue<HObject>();
            rightCamera.ImageCallbackFunc = ImageCallbackFunc2;
        }
        #endregion
        #region 功能函数
        private void NlogConfig()
        {
            var config = new NLog.Config.LoggingConfiguration();

            // Targets where to log to: File and Console
            var logfile = new NLog.Targets.FileTarget("logfile") { FileName = "${basedir}/logs/${shortdate}.log", Layout = "${longdate}|${level:uppercase=true}|${message}" };
            var logconsole = new NLog.Targets.ConsoleTarget("logconsole");

            // Rules for mapping loggers to targets            
            config.AddRule(NLog.LogLevel.Info, NLog.LogLevel.Fatal, logconsole);
            config.AddRule(NLog.LogLevel.Debug, NLog.LogLevel.Fatal, logfile);

            // Apply config           
            NLog.LogManager.Configuration = config;
        }
        private void addMessage(string str)
        {
            logger.Info(str);
            string[] s = MessageStr.Split('\n');
            if (s.Length > 1000)
            {
                MessageStr = "";
            }
            if (MessageStr != "")
            {
                MessageStr += "\n";
            }
            MessageStr += DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " " + str;
        }
        #endregion
    }
}
